package org.ocean.online.utils;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONObject;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.wicket.protocol.http.servlet.MultipartServletWebRequest;
import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
import org.apache.wicket.request.Request;
import org.apache.wicket.request.Response;
import org.apache.wicket.util.upload.FileItem;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.ocean.online.sys.inner.IO;
import org.ocean.online.sys.inner.Req;
import org.ocean.online.sys.inner.Res;
import org.ocean.online.sys.inner.Sys;

public class RenderUtil {

	public static void renderView(Request request, Response res,String fullPath) {
		Map params = ParamUtil.toMap(request.getRequestParameters());
		JSONObject data = new JSONObject();
		data.putAll(params);
		String view="";
		try {
			view = readViewContent(fullPath);
		} catch (FileNotFoundException e) {
			res.write("404");
			return ;
		}
		Document doc = Jsoup.parse(view );
		String hiddenParams = "<span id='pageData' style='display:none'>"+data.toString()+"</span>";
		doc.getElementsByTag("body").append(hiddenParams);
		HttpServletResponse httpResponse = (HttpServletResponse) res.getContainerResponse();
		httpResponse.setContentType("text/html");
		res.write(doc.html().getBytes());
	}
	
	public static void renderAction(ScriptEngine engine,Request request, Response res,String fullPath) {
//		System.out.println(path);
		String username = UserUtil.getUsernameFromRequest(request);
		Bindings bindings = prepareBindings(engine,request,res,username,fullPath);
		engine.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
		String script;
		Object result="";
		File file = new File(fullPath);
		try {
			// 执行脚本
			script = FileUtils.readFileToString(file);
//			if(script.contains("java.io")){
//				throw new RuntimeException("java.io is forbiden,user sys.io instead");
//			}
			result = engine.eval(script);
//			System.out.println("result of action is : "+result);
		} catch (IOException e1) {
			throw new RuntimeException(e1);
		}catch (ScriptException e) {
			e.printStackTrace();
			result="error in action "+file.getName()+" "+e.getMessage();
		}finally{
			if(result==null){
				// 从哪来到哪去
//				HttpServletRequest servletRequest = ((ServletWebRequest) request).getContainerRequest();
//				String refer = servletRequest.getHeader("referer");
//				result = "<script type='text/javascript'>window.location='"+refer+"'</script>";
				return;
			}
			if(result.getClass().getName().equals("sun.org.mozilla.javascript.internal.InterpretedFunction")){
				System.out.println("result of action is  InterpretedFunction");
				return;
			}
			res.write(result.toString().getBytes());
		}
	}
	
	private static Bindings prepareBindings(ScriptEngine engine, Request request,Response res
			,String username,String fullPath) {
		Bindings bindings = engine.createBindings();
		Sys sys = new Sys();
		sys.setDb(UserUtil.getDb(username));
		sys.setIo(new IO(""));
		sys.setEngine(engine);
		Req req = new Req();
		req.setParams(ParamUtil.toMap(request.getRequestParameters()));
		if(request instanceof MultipartServletWebRequest){
			List list = processUpload((MultipartServletWebRequest)request);
			req.setFiles(list);
		}
		HttpServletRequest servletRequest = ((ServletWebRequest) request).getContainerRequest();
		req.setHttpServletRequest(servletRequest);
		
		bindings.put("sys", sys);
		bindings.put("req", req);
		bindings.put("res", new Res(res,username).setFullFilePath(fullPath));
		bindings.put("engine", engine);
		return bindings;
	}

	public static String readViewContent(String fullPath) throws FileNotFoundException {
		String content = "";
		try {
			content = FileUtils.readFileToString(new File(fullPath),"utf-8");
		}catch(FileNotFoundException e){
			throw e;
		}
		catch (IOException e) {
			throw new RuntimeException("read view"+fullPath+" error",e);
		}
		return parseImport(fullPath,content);
	}
	private static String parseImport(String parentPath,String view){
		Document doc = Jsoup.parse(view);
		Elements imports = doc.getElementsByTag("import");
		for(int i=0;i<imports.size();i++){
			Element elem = imports.get(i);
			File parent = new File(parentPath);
			String src= elem.attr("src");
			if(StringUtils.isEmpty(src)){
				continue;
			}
			String content="";
			try {
				content = readViewContent(parent.getParent()+File.separator+src);
			} catch (FileNotFoundException e) {
				content="<div>"+src+" 404"+"</div>";
			} 
			elem.after(content);
			elem.remove();
		}
		return doc.html();
	}
	
	private static List processUpload(MultipartServletWebRequest req) {
		Collection<List<FileItem>> files = req.getFiles().values();
		List fileList = new ArrayList();
		for(List<FileItem> list:files){
			for(FileItem fi : list){
				fileList.add(fi);
			}
		}
		return fileList;
	}
}
